from typing import List, Optional

from fastapi import HTTPException
from sqlalchemy.ext.asyncio import AsyncSession

from exceptions.exception import ServiceException
from module_admin.entity.vo.common_vo import CrudResponseModel
from module_kylin.dao.future_account_dao import FutureAccountDao
from module_kylin.entity.vo.future_account_vo import (
    FutureAccountModel,
    FutureAccountPageQueryModel,
    DeleteFutureAccountModel
)
from utils.common_util import CamelCaseUtil
from utils.log_util import logger


class FutureAccountService:
    """
    期货账户服务层
    """

    @classmethod
    async def get_account_list_services(
            cls, query_db: AsyncSession, query_object: FutureAccountPageQueryModel, is_page: bool = False):
        """
        获取期货账户列表信息service

        :param query_db: orm对象
        :param query_object: 查询参数对象
        :param is_page: 是否开启分页
        :return: 期货账户列表信息对象
        """
        account_list_result = await FutureAccountDao.get_account_list(query_db, query_object, is_page)

        return account_list_result

    @classmethod
    async def account_detail_services(cls, query_db: AsyncSession, account_id: int):
        """
        获取期货账户详细信息service

        :param query_db: orm对象
        :param account_id: 账户主键id
        :return: 账户id对应的信息
        """
        account = await FutureAccountDao.get_account_by_id(query_db, account_id=account_id)
        if account:
            result = FutureAccountModel(**CamelCaseUtil.transform_result(account))
        else:
            result = FutureAccountModel(**dict())

        return result

    @classmethod
    async def check_account_unique_services(cls, query_db: AsyncSession, page_object: FutureAccountModel):
        """
        校验账户唯一性service

        :param query_db: orm对象
        :param page_object: 账户对象
        :return: 账户是否唯一
        """
        # 账户名称唯一性校验
        account_info = await FutureAccountDao.get_account_by_name(query_db, page_object.account_name)
        if account_info and page_object.id != account_info.id:
            return False
        # 结算单账号唯一性校验
        accounts = await FutureAccountDao.get_account_list(
            query_db, 
            FutureAccountPageQueryModel(settlement_account=page_object.settlement_account),
            is_page=False
        )
        for account in accounts:
            # 确保账户的结算单账号存在且与当前对象的结算单账号匹配
            if account.settlement_account and page_object.settlement_account:
                # 对于新增操作，只要存在相同结算单账号就返回False
                # 对于编辑操作，只要存在不同ID的相同结算单账号就返回False
                if account.settlement_account == page_object.settlement_account and \
                   (page_object.id is None or account.id != page_object.id):
                    return False
        return True

    @classmethod
    async def add_account_services(cls, query_db: AsyncSession, page_object: FutureAccountModel):
        """
        新增期货账户信息service

        :param query_db: orm对象
        :param page_object: 新增账户对象
        :return: 新增账户校验结果
        """
        if not await cls.check_account_unique_services(query_db, page_object):
            raise ServiceException (
                message=f'新增账户{page_object.account_name}失败，账户名称或结算单账号已存在')
        else:
            try:
                await FutureAccountDao.add_account(query_db, page_object)
                await query_db.commit()
                return CrudResponseModel(is_success=True, message='新增成功')
            except Exception as e:
                await query_db.rollback()
                raise e

    @classmethod
    async def edit_account_services(cls, query_db: AsyncSession, page_object: FutureAccountModel):
        """
        编辑期货账户信息service

        :param query_db: orm对象
        :param page_object: 编辑账户对象
        :return: 编辑账户校验结果
        """
        edit_account = page_object.model_dump(exclude_unset=True)
        account_info = await cls.account_detail_services(query_db, page_object.id)
        if account_info.id:
            if not await cls.check_account_unique_services(query_db, page_object):
                raise ServiceException(
                    message=f'修改账户{page_object.account_name}失败，账户名称或结算单账号已存在')
            else:
                try:
                    await FutureAccountDao.update_account(query_db, page_object.id, page_object)
                    await query_db.commit()
                    return CrudResponseModel(is_success=True, message='更新成功')
                except Exception as e:
                    await query_db.rollback()
                    raise e
        else:
            raise ServiceException(message='期货账户不存在')

    @classmethod
    async def delete_account_services(cls, query_db: AsyncSession, page_object: DeleteFutureAccountModel):
        """
        删除期货账户信息service

        :param query_db: orm对象
        :param page_object: 删除账户对象
        :return: 删除账户校验结果
        """
        try:
            # 获取需要删除的账户id列表
            delete_ids = []
            if page_object.ids:
                delete_ids.extend(page_object.ids)
            if page_object.account_names:
                for account_name in page_object.account_names:
                    account = await FutureAccountDao.get_account_by_name(query_db, account_name)
                    if account:
                        delete_ids.append(account.id)
            
            if delete_ids:
                # 删除重复的id
                delete_ids = list(set(delete_ids))
                await FutureAccountDao.delete_account(query_db, delete_ids)
                await query_db.commit()
                return CrudResponseModel(is_success=True, message='删除成功')
            else:
                raise ServiceException(message='请选择要删除的账户')
        except Exception as e:
            await query_db.rollback()
            raise e

    @classmethod
    async def get_all_accounts(cls, query_db: AsyncSession):
        """
        获取所有期货账户

        :param query_db: orm对象
        :return: 期货账户列表
        """
        accounts = await FutureAccountDao.get_account_list(
            query_db, 
            FutureAccountPageQueryModel(),
            is_page=False
        )
        return accounts